using System.Data;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.ServiceObjects;

namespace OracleInternal.BulkCopy
{
	internal abstract class BulkCopySourceDotNetTypes : BulkCopyDataSource
	{
		protected OracleParameterCollection m_columns;

		internal BulkCopySourceDotNetTypes(OracleBulkCopy bulkCopy, int requestedBatchSize)
			: base(bulkCopy, requestedBatchSize)
		{
			m_columns = new OracleParameterCollection();
		}

		private int GetOneRow(OracleBulkCopyColumnMappingCollection internalColumnMappings, int rowIndex, BulkCopyRows bulkCopyRows)
		{
			if (PopulateRows(internalColumnMappings, 1) <= 0)
			{
				return 0;
			}
			BulkCopyBindingRow bindingRow = GetBindingRow(rowIndex, bulkCopyRows);
			OracleConnectionImpl oracleConnectionImpl = m_bulkCopy.Connection.m_oracleConnectionImpl;
			int num = 0;
			bool bMetadataModified = false;
			foreach (OracleParameter column in m_columns)
			{
				column.m_bArrayBind = false;
				column.PreBind(oracleConnectionImpl, m_columnsMetaData[num], ref bMetadataModified, 0, out var _, out var paramValue, isEFSelectStatement: false, SqlStatementType.DML);
				if (column.IsBindNullValue())
				{
					bindingRow.m_col_nullIndicators[num] = true;
					bindingRow.m_columnsBindValues[num] = null;
					bindingRow.m_bindValuesLen[num] = 0;
				}
				else
				{
					bindingRow.m_col_nullIndicators[num] = false;
					if (paramValue != null)
					{
						byte[] array = (byte[])paramValue;
						bindingRow.m_columnsBindValues[num] = array;
						bindingRow.m_bindValuesLen[num] = array.Length;
					}
					else
					{
						bindingRow.m_columnsBindValues[num] = null;
						bindingRow.m_bindValuesLen[num] = 0;
					}
				}
				num++;
			}
			bulkCopyRows.m_numOfRowsProcessed++;
			return 1;
		}

		private void CheckSourceValues(int numOfRows)
		{
			for (int i = 0; i < m_columns.Count; i++)
			{
				if (m_columnsMetaData[i].m_dataType == 113 && m_columns[i].OracleDbType == OracleDbType.LongRaw && GetSrcColumnType(i) == typeof(string))
				{
					m_columns[i].OracleDbType = OracleDbType.NChar;
				}
			}
		}

		private int GetArrayRows(OracleBulkCopyColumnMappingCollection internalColumnMappings, int numOfRows, BulkCopyRows bulkCopyRows)
		{
			int num = 0;
			int i = 0;
			BulkCopyBindingRow bulkCopyBindingRow = null;
			num = PopulateRows(internalColumnMappings, numOfRows);
			if (num <= 0)
			{
				return 0;
			}
			CheckSourceValues(num);
			object[] array = new object[m_columns.Count];
			OracleConnectionImpl oracleConnectionImpl = m_bulkCopy.Connection.m_oracleConnectionImpl;
			bool bMetadataModified = false;
			for (int j = 0; j < m_columns.Count; j++)
			{
				m_columns[j].m_bArrayBind = true;
				m_columns[j].PreBind(oracleConnectionImpl, m_columnsMetaData[j], ref bMetadataModified, num, out var _, out var paramValue, isEFSelectStatement: false, SqlStatementType.DML);
				array[j] = paramValue;
			}
			byte[] array2 = null;
			for (; i < num; i++)
			{
				bulkCopyBindingRow = GetBindingRow(i, bulkCopyRows);
				for (int k = 0; k < m_columns.Count; k++)
				{
					if (m_columns[k].IsArrayBindNullValue(i))
					{
						bulkCopyBindingRow.m_col_nullIndicators[k] = true;
						bulkCopyBindingRow.m_columnsBindValues[k] = null;
						bulkCopyBindingRow.m_bindValuesLen[k] = 0;
						continue;
					}
					bulkCopyBindingRow.m_col_nullIndicators[k] = false;
					array2 = ((byte[][])array[k])[i];
					if (array2 != null || array2.Length != 0)
					{
						bulkCopyBindingRow.m_columnsBindValues[k] = array2;
						bulkCopyBindingRow.m_bindValuesLen[k] = array2.Length;
					}
					else
					{
						bulkCopyBindingRow.m_columnsBindValues[k] = null;
						bulkCopyBindingRow.m_bindValuesLen[k] = 0;
					}
				}
			}
			bulkCopyRows.m_numOfRowsProcessed += num;
			return num;
		}

		public override void Initialize(ColumnDescribeInfo[] destinationColumnsMetaData)
		{
			m_columnsMetaData = destinationColumnsMetaData;
			ColumnDescribeInfo[] columnsMetaData = m_columnsMetaData;
			foreach (ColumnDescribeInfo columnDescribeInfo in columnsMetaData)
			{
				OracleParameter oracleParameter = new OracleParameter();
				oracleParameter.ParameterName = columnDescribeInfo.pColAlias;
				oracleParameter.OracleDbType = (OracleDbType)OraDb_DbTypeTable.oraTypeToOracleDbTypeMapping[columnDescribeInfo.m_dataType];
				oracleParameter.m_bArrayBind = false;
				oracleParameter.Direction = ParameterDirection.Input;
				switch (oracleParameter.OracleDbType)
				{
				case OracleDbType.Clob:
				case OracleDbType.NClob:
					oracleParameter.OracleDbType = OracleDbType.NChar;
					break;
				case OracleDbType.Blob:
					oracleParameter.OracleDbType = OracleDbType.LongRaw;
					break;
				case OracleDbType.Json:
					oracleParameter.OracleDbType = OracleDbType.NChar;
					break;
				case OracleDbType.Char:
				case OracleDbType.NChar:
				case OracleDbType.NVarchar2:
				case OracleDbType.Raw:
				case OracleDbType.Varchar2:
					oracleParameter.Size = columnDescribeInfo.m_maxLength;
					break;
				case OracleDbType.Byte:
				case OracleDbType.Decimal:
				case OracleDbType.Double:
				case OracleDbType.Int16:
				case OracleDbType.Int32:
				case OracleDbType.Int64:
				case OracleDbType.Single:
				case OracleDbType.BinaryDouble:
				case OracleDbType.BinaryFloat:
					oracleParameter.Precision = (byte)columnDescribeInfo.m_precision;
					oracleParameter.Scale = (byte)columnDescribeInfo.m_scale;
					break;
				case OracleDbType.TimeStampTZ:
					oracleParameter.SkipConversionToLocalTime = true;
					break;
				}
				m_columns.Add(oracleParameter);
			}
		}

		public override int GetRows(OracleBulkCopyColumnMappingCollection internalColumnMappings, int numOfRows, ref BulkCopyRows bulkCopyRows)
		{
			if (numOfRows == 1)
			{
				return GetOneRow(internalColumnMappings, 0, bulkCopyRows);
			}
			return GetArrayRows(internalColumnMappings, numOfRows, bulkCopyRows);
		}
	}
}
